home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’96 / Talking Telnet / source / FTPserver / bkgr.c < prev    next >
Text File  |  1996-06-22  |  30KB  |  1,108 lines

  1. /*    Background procedures for rcp and ftp
  2. *****************************************************************
  3. *    NCSA Telnet for the Macintosh                                *
  4. *                                                                *
  5. *    National Center for Supercomputing Applications                *
  6. *    Software Development Group                                    *
  7. *    152 Computing Applications Building                            *
  8. *    605 E. Springfield Ave.                                        *
  9. *    Champaign, IL  61820                                        *
  10. *                                                                *
  11. *    Copyright (c) 1986-1992,                                    *
  12. *    Board of Trustees of the University of Illinois                *
  13. *****************************************************************
  14. * Revisions:
  15. * 11/86          Tim Krauskopf
  16. * 7/92    Telnet 2.6: added global structures, cleaned up defines   Scott Bulmahn
  17. *
  18. *
  19. */
  20.  
  21.  
  22. #ifdef MPW
  23. #pragma segment FTPServer
  24. #endif
  25.  
  26.  
  27. #include "InternalEvents.h"
  28. #include "netevent.proto.h"
  29. #include "menuseg.proto.h"
  30. #include "network.proto.h"
  31. #include "mydnr.proto.h"
  32. #include "macutil.proto.h"
  33. #include "macbinary.h"
  34. #include "binsubs.proto.h"
  35. #include "maclook.proto.h"
  36. #include "bkgr.proto.h"
  37. #include "telneterrors.h"
  38. #include "wind.h"
  39. #include "mainseg.proto.h"
  40. #include "translate.proto.h"
  41. #include "DlogUtils.proto.h"        // For WriteZero proto
  42.  
  43. #include "vsdata.h"
  44. #include "vsinterf.proto.h"
  45.  
  46. extern WindRec *ftplog;
  47. extern TelInfoRec *TelInfo;
  48.  
  49. #define PFTP 1
  50. #define PRCP 2
  51. #define PDATA 3
  52. #define HTELNET 23
  53. #define HRSHD 514
  54. #define HFTP 21
  55. #define BUFFERS 8000
  56. #define PATHLEN 256
  57. #define MACBINARY
  58. #define RCPSEGSIZE 512
  59. #define O_RAW O_RDONLY
  60. #define EOLCHAR 13
  61. #define FASCII 0
  62. #define FIMAGE O_RAW
  63. #define FAMODE 0
  64. #define FIMODE 1
  65. #define FMMODE 2            /* Mac Binary, when ready */
  66.  
  67. MBFile
  68.     *mbfp=NULL;
  69.  
  70. char *nextfile;
  71.  
  72. static Handle mungbuf = 0;
  73.  
  74. static short fcnt=0;
  75. static  short
  76.     ftpenable=0,                /* is file transfer enabled? */
  77.     rcpenable=0,                /* is rcp enabled? */
  78.     rsnum=-1,                    /* port number for incoming rshell */
  79.     rserr=-1;                    /* port number for rshd() stderr */
  80.  
  81. static  unsigned char *xs=0L,    /* buffer space for file transfer */
  82.         *pathname=0L,            /* space to keep path names */
  83.         *newfile=0L,            /* current file being received */
  84.         myuser[17],                    /* user name on my machine */
  85.         waitchar;                    /* character waiting for from net */
  86.  
  87. static short 
  88.     curstate = -1,            /* state machine for background processes */
  89.     retstate = 200,            /* to emulate a subroutine call */
  90.     ftpstate = 0,            /* state of the ftp data transfer */
  91.     isdir=0,                /* flag for rcp target pathname */
  92.     waitpos=0,                /* marker for gathering strings from net */
  93.     cnt=0,                    /* number of characters from last netread() */
  94.     fh=0,                    /* file handle when transfer file is open */
  95.     ftpfh=0,                /* file handle for ftp data */
  96.     rc=0,                    /* telnet flag */
  97.     xp=0,                    /* general pointer */
  98.     towrite=0,                /* file transfer pointer */
  99.     len=0;                    /* file transfer length */
  100.  
  101. static long
  102.     filelen=0L;                /* length of current file for transfer */
  103.  
  104. short mainport[NPORTS];        /* BYU 2.4.16 - map FTP data port to main port */
  105. short dataport[NPORTS];        /* BYU 2.4.16 - map FTP main port to data port */
  106. short mainstate[NPORTS];    /* BYU 2.4.16 */
  107. short datastate[NPORTS];    /* BYU 2.4.16 */
  108. short retnstate[NPORTS];
  109.  
  110. ip_port    fileport[NPORTS];
  111.  
  112. static char crfound=0;
  113.  
  114. static short rfstate,
  115.     ftptmode=FAMODE;            /* how to transfer the file on net */
  116.  
  117. static    ip_addr    portaddr[NPORTS],
  118.                 hishostaddr;
  119. static    ip_port    portremoteport[NPORTS],
  120.                 portlocalport[NPORTS];
  121.                 
  122. unsigned char messs[100];        /* BYU */
  123.  
  124. char    ListingTemplate[256];
  125. CInfoPBRec    theDirectoryState;
  126.  
  127. static    void CRESP(short fnum, short msg_number);
  128. static    short ftpgo( short fnum);
  129.  
  130. void    FTPServerUnload(void) {}
  131.  
  132. void CRESP(short fnum, short msg_number)
  133. {
  134.   GetIndString(messs,MSG_RESOURCE_ID,msg_number+1);
  135.   netpush(fnum);
  136.   netwrite(fnum, &messs[1], (short)messs[0]);
  137. }
  138.  
  139. void ftpmess( char *cp)
  140. {
  141.     short temp;
  142.     temp=strlen(cp);
  143.     if (temp>80 || temp < 1) return;
  144.     VSwrite(ftplog->vs,cp,temp);
  145. }
  146.  
  147. /***********************************************************************/
  148. void StartUpFTP(void)
  149. {
  150.     if (gFTPServerPrefs->ServerState != 0)
  151.         setftp();
  152.     else
  153.         unsetftp();
  154. }
  155.  
  156. void setftp( void)
  157. {
  158.     short fnum,i1;                            /* BYU 2.4.16 */
  159.     short size = 1024;
  160. /* set up to receive a telnet connection for ftp commands */
  161.     rfstate = 0;
  162.     ftpstate = 0;
  163. /* Listen for FTP if we're not listening already */
  164.  
  165.     for (i1 = 0; i1 < NPORTS; i1++)                                         /* BYU 2.4.16 */
  166.         if (GetPortType(i1) == PFTP)
  167.             break;                                                            /* BYU 2.4.16 */
  168.  
  169.     if (i1 >= NPORTS) {                                /* BYU 2.4.16 - non-SLIP listen */
  170.         fnum = netlisten(HFTP);        /* BYU 2.4.16 - MacTCP listen */
  171.         ftpenable = 1;                                /* BYU 2.4.16 */
  172.  
  173.         if (fnum >= 0) {                            /* BYU 2.4.16 - signal that events should be caught */
  174.             SetPortType(fnum, PFTP);
  175.             dataport[fnum] = -1;                    /* BYU 2.4.16 - no data needed yet */
  176.             mainstate[fnum] = 0;                    /* BYU 2.4.16 */
  177.             datastate[fnum] = 0;                    /* BYU 2.4.16*/
  178.             retnstate[fnum] = 200;                    /* BYU 2.4.16 */
  179.         }                                            /* BYU 2.4.16 */
  180.     }                                                /* BYU 2.4.16 */
  181.  
  182.     strcpy((char *) myuser,"unknown");                /* BYU LSC - set unknown user name */
  183.     
  184.     if (mungbuf == NULL)
  185.         mungbuf = myNewHandle(size);
  186.     }
  187.  
  188. void unsetftp( void)
  189. {
  190.     short i1;                            /* BYU 2.4.16 */
  191.  
  192.     rfstate = 0;
  193.     ftpstate = 0;
  194.     for (i1 = 0; i1 < NPORTS; i1++) {    /* BYU 2.4.16 */
  195.         if (GetPortType(i1) == PFTP) {        /* BYU 2.4.16 */
  196.             netclose(i1);                /* BYU 2.4.16 */
  197.             SetPortType(i1, NO_TYPE);            /* BYU 2.4.16 */
  198.             mainstate[i1] = 0;            /* BYU 2.4.16 */
  199.             datastate[i1] = 0;            /* BYU 2.4.16*/
  200.         }                                /* BYU 2.4.16 */
  201.     }                                    /* BYU 2.4.16 */
  202.     ftpenable = 0;
  203.     if (mungbuf != NULL)
  204.         DisposeHandle(mungbuf);
  205. }
  206.  
  207.  
  208. #if 0        /* BYU - Converted to STR# resource number 23227 */
  209. /***********************************************************************/
  210. /*
  211. *  resident ftp server -- enables initiation of ftp without a username
  212. *  and password, as long as this telnet is active at the same time
  213. *  Now checks for the need of passwords.
  214. */
  215.  
  216. static char *messs[] = {
  217.                         "220 Macintosh Resident FTP server, ready \015\012",
  218.                         "451 Error in processing list command \015\012",
  219.                         "221 Goodbye \015\012",                        /*2*/
  220.                         "200 This space intentionally left blank <   > \015\012",
  221.                         "150 Opening connection \015\012",
  222.                         "226 Transfer complete \015\012",            /*5*/
  223.                         "200 Type set to A, ASCII transfer mode \015\012",
  224.                         "200 Type set to I, binary transfer mode \015\012",
  225.                         "500 Command not understood \015\012",        /*8*/
  226.                         "200 Okay \015\012",
  227.                         "230 User logged in \015\012",
  228.                         "550 File not found \015\012",                /*11*/
  229.                         "501 Directory not present or syntax error\015\012",
  230.                         "250 Chdir okay\015\012",
  231.                         "257 \"",
  232.                         "\" is the current directory \015\012",        /*15*/
  233.                         "501 File not found \015\012",
  234.                         "504 Parameter not accepted, not implemented\015\012",
  235.                         "200 Stru F, file structure\015\012",
  236.                         "200 Mode S, stream mode\015\012",        /*19*/
  237.                         "202 Allocate and Account not required for this server\015\012",
  238.                         "501 Cannot open file to write, check for valid name\015\012",
  239.                         "530 USER and PASS required to activate me\015\012",
  240.                         "331 Password required\015\012",      /*23 */
  241.                         "530 Login failed\015\012",
  242.                         "200 MacBinary Mode enabled\015\012",
  243.                         "200 MacBinary Mode disabled\015\012",  /*26 */
  244.                         "552 Disk write error, probably disk full\015\012",
  245.                         "214-NCSA Telnet FTP server, supported commands:\015\012",
  246.                         "    USER  PORT  RETR  ALLO  PASS  STOR  CWD  XCWD  XPWD  LIST  NLST\015\012",
  247.                         "    HELP  QUIT  MODE  TYPE  STRU  ACCT  NOOP  MACB\015\012",  /*30*/
  248.                         "    MACB is MacBinary and must be done with TYPE I\015\012",
  249.                         "214 Direct comments and bugs to telbug@ncsa.uiuc.edu\015\012",
  250.                         "200 Type set to I, binary transfer mode [MACBINARY ENABLED]\015\012",                /* 33 */
  251.                         "200 Type set to I, binary transfer mode [macbinary disabled]\015\012",
  252.                 ""};
  253.  
  254. #endif
  255.  
  256. /* open the FTP data connection to the remote host */
  257. short ftpgo( short fnum)
  258. {
  259.     short    ftpdata;
  260.  
  261.     netfromport(20);                 /* ftp data port */
  262.     ftpdata = netxopen(portaddr[fnum],fileport[fnum], 15);
  263.     mainport[ftpdata] = fnum;
  264.     dataport[fnum] = ftpdata;
  265.     return(ftpdata);
  266. }
  267.  
  268. void rftpd
  269.   (
  270.     short code,                                /* BYU 2.4.16 */
  271.     short fnum                                /* BYU 2.4.16 */
  272.   )
  273. {
  274.     ip_port    fdport;
  275.     short    ftpdata, i, append = 0;
  276.     char    tempp[256], theDir[256];
  277.     char updir[4];                        /* JMB 2.6 */
  278.     
  279.     if (!ftpenable)
  280.         return;
  281.  
  282.     netpush(fnum);
  283.  
  284.     rfstate = mainstate[fnum];                /* BYU 2.4.16 */
  285.     ftpstate = datastate[fnum];                /* BYU 2.4.16 */
  286.     retstate = retnstate[fnum];                /* BYU 2.4.16 */
  287.     fdport = fileport[fnum];                /* BYU 2.4.16 */
  288.  
  289.     switch (rfstate) {
  290.         case 0:
  291.             if (code != CONOPEN) 
  292.                 break;
  293.             ftptmode = FAMODE;
  294.             netputevent(USERCLASS,FTPCOPEN,-1,0);
  295.             if (!xs) xs=(unsigned char *)myNewPtr(BUFFERS+10);    /* BYU LSC */
  296.             if (!pathname) pathname=(unsigned char *)myNewPtr(PATHLEN);
  297.             if (!newfile) newfile=(unsigned char *)myNewPtr(PATHLEN);
  298.             if (!xs || !pathname || !newfile)    /* no memory for ftp names */
  299.                 {
  300.                 DoError(114 | MEMORY_ERRORCLASS, LEVEL3, NULL);
  301.                 quit();                    // Should we really quit?
  302.                 }    
  303.         
  304.             rfstate = 1;                /* drop through */
  305.         case 1:
  306.             CRESP(fnum,0);                            /* BYU 2.4.16 */
  307.             netgetftp(fnum, &portaddr[fnum], &portlocalport[fnum], &portremoteport[fnum]);        /* BYU 2.4.16 - get default ftp information */
  308.             hishostaddr = portaddr[fnum];
  309.             fdport = portremoteport[fnum];
  310.  
  311.             waitpos = 0; waitchar = '\012';
  312.             rfstate = 50;               /* note skips over */
  313.             if ((gFTPServerPrefs->ServerState == 2)) 
  314.                 retstate = 3;                /* check pass */
  315.             else
  316.                 retstate = 5;                /* who needs one ? */
  317.             break;
  318.         case 3:                /* check for passwords */
  319.         case 4:
  320.             waitpos = 0;  waitchar = '\012';
  321.             rfstate = 50;  
  322.             if (!strncmp("USER",(char *) xs,4)) {    /* BYU LSC */
  323.                 if (strlen((char *) xs) < 6)        /* BYU LSC - make sure blank name stays blank */
  324.                     xs[5] = myuser[0] = 0;
  325.                 strncpy((char *) myuser,(char *) &xs[5],16);        /* BYU LSC - keep user name */
  326.                 FTPLogUserLoggingIn();
  327.                 CRESP(fnum,23);                                        /* BYU 2.4.16 */
  328.                 retstate = 4;        /* wait for password */
  329.                 break;
  330.             }
  331.             if (!strncmp("PASS",(char *) xs,4)) {                    /* BYU LSC */
  332.                 if (Scheckpass((char *) myuser,(char *) &xs[5])) {    /* BYU LSC */
  333.                     ftpmess("FTP password OK - logged in\015\012");
  334.                     CRESP(fnum,10);                                    /* BYU 2.4.16 */
  335.                     retstate = 5;
  336.                 }
  337.                 else {
  338.                     ftpmess("FTP password failed - access denied\015\012");
  339.                     CRESP(fnum,24);                                    /* BYU 2.4.16 */
  340.                     retstate = 3;
  341.                 }
  342.                 break;
  343.             }
  344.             if (!strncmp("QUIT",(char *) xs,4)) {    /* BYU LSC */
  345.                 CRESP(fnum,2);                        /* BYU 2.4.16 */
  346.                 cnt = -1;
  347.             }
  348.             else {
  349.                 CRESP(fnum,22);        /* BYU 2.4.16 */
  350.             }
  351.             retstate = 3;            /* must have password first */
  352.             break;                
  353.                 
  354. /* interpret commands that are received from the other side */
  355.             
  356.         case 5:
  357.  
  358. /* set to a safe state to handle recursion, wait for another command line from client */
  359.             rfstate = 50;
  360.             retstate = 5;
  361.             waitchar = '\012';
  362.             waitpos = 0;
  363.  
  364.             if (!strncmp((char *) xs,"LIST",4) || !strncmp((char *) xs,"NLST",4)) {    /* BYU LSC */
  365.                 if ((strlen((char *) xs) < 6) || xs[5] == '.')        /* BYU LSC */
  366.                     strcpy((char *) xs,"LIST *");                    /* BYU LSC */
  367.                 strcpy(ListingTemplate, (char *) &xs[5]);
  368.  
  369.                 theDirectoryState.hFileInfo.ioFDirIndex=1;
  370.                 theDirectoryState.hFileInfo.ioVRefNum = TelInfo->DefaultDirVRefNum;
  371.                 theDirectoryState.hFileInfo.ioDirID = TelInfo->DefaultDirDirID;
  372.  
  373.                 nextfile = getFileName(ListingTemplate, &theDirectoryState);    /* find first name */
  374.                 if (nextfile == NULL) {
  375.                     CRESP(fnum,16);                /* BYU 2.4.16 */
  376.                 }
  377.                 else {
  378.                     Str255    tempstr;
  379.                     char    tempstr2[256];
  380.                     ftpdata = ftpgo(fnum);                /* BYU 2.4.16 - open the connection */
  381.                     fdport = portremoteport[fnum]; /* BYU 2.4.16 - reset to def */
  382.  
  383.                     if (ftpdata >= 0)
  384.                         SetPortType(ftpdata, PDATA);
  385.                     ftpstate = 40;        /* ready to transmit */
  386.                     CRESP(fnum,4);                            /* BYU 2.4.16 */
  387.                     PathNameFromDirID(TelInfo->DefaultDirDirID, TelInfo->DefaultDirVRefNum, tempstr);
  388.                     PtoCstr(tempstr);
  389.                     sprintf(tempstr2, "FTP Sending Directory %s\015\012", (char *)tempstr);
  390.                     ftpmess(tempstr2);
  391.                 }
  392.             }
  393.             else if (!strncmp((char *) xs,"CWD",3)) {    /* BYU LSC */
  394.                 if (ChangeDirectory(&(TelInfo->DefaultDirDirID), &(TelInfo->DefaultDirVRefNum), (char *) &xs[4])) {
  395.                     CRESP(fnum,12);                        /* BYU 2.4.16 */
  396.                 }
  397.                 else {                        /* success */
  398.                     CRESP(fnum,13);            /* BYU 2.4.16 */
  399.                 }
  400.             }
  401.             else if (!strncmp((char *) xs,"CDUP",4)) {        /* JMB 2.6 */
  402.                 strcpy(updir, "..");                        /* JMB 2.6 */
  403.                 if (ChangeDirectory(&(TelInfo->DefaultDirDirID), &(TelInfo->DefaultDirVRefNum), updir)) {                /* JMB 2.6 */
  404.                     CRESP(fnum,12);                            /* JMB 2.6 */
  405.                 }                                            /* JMB 2.6 */
  406.                 else {                                        /* JMB 2.6 */
  407.                     CRESP(fnum,13);                            /* JMB 2.6 */
  408.                 }                                            /* JMB 2.6 */
  409.             }                                                /* JMB 2.6 */
  410.             else if (!strncmp((char *) xs,"STOR",4) || !strncmp((char *) xs,"APPE", 4))
  411.               {
  412.                 short    MBflag;
  413.  
  414.                 if (!strncmp((char *) xs,"APPE", 4)) {
  415.                     if (ftptmode != FASCII) {
  416.                         CRESP(fnum, 35);
  417.                         break;
  418.                         }
  419.                     else
  420.                         append = 1;
  421.                     }
  422.                     
  423.                 /* had to simplify this, else MPW C 3.0/3.1 generates bad code! */
  424.                 if ((!TelInfo->MacBinary) || (ftptmode == FAMODE))
  425.                     MBflag = MB_DISABLE;
  426.                 else
  427.                     MBflag = 0;
  428.                     
  429.                 if (ftptmode == FAMODE)    MBflag |= MB_ISASCII;
  430.                 if (append) MBflag |= MB_APPEND;
  431.                 append = 0;
  432.                 
  433.                 mbfp = MBopen((char *)&xs[5], TelInfo->DefaultDirVRefNum, TelInfo->DefaultDirDirID, (short)(MB_WRITE | MBflag));
  434.                 if (mbfp == 0L)
  435.                   {
  436.                     CRESP(fnum,21);            /* BYU 2.4.16 */
  437.                     break;
  438.                   }
  439.                 else
  440.                     ftpfh = 12;
  441.  
  442.                 ftpstate = 0;
  443.  
  444.                 strncpy((char *) newfile,(char *) &xs[5],PATHLEN-1);    /* BYU LSC */
  445.                 
  446.  
  447.                 ftpdata = ftpgo(fnum);                /* BYU 2.4.16 - open connection */
  448.                 fdport = portremoteport[fnum]; /* BYU 2.4.16 - reset to def */
  449.  
  450.                 if (ftpdata >= 0)
  451.                     SetPortType(ftpdata, PDATA);
  452.  
  453.                 CRESP(fnum,4);        /* BYU 2.4.16 */
  454.  
  455.                 ftpstate = 30;        /* ready for data */
  456.               }
  457.  
  458.             else if (!strncmp((char *) xs,"RETR",4))    /* BYU LSC */
  459.               {
  460.               /* had to simplify this, else MPW C 3.0/3.1 generates bad code! */
  461.                 short
  462.                     MBflag;
  463.                 if ((!TelInfo->MacBinary) || (ftptmode == FAMODE))
  464.                     MBflag = MB_DISABLE;
  465.                 else
  466.                     MBflag = 0;
  467.                     
  468.                 if (ftptmode == FAMODE)    MBflag |= MB_ISASCII;
  469.                 
  470.                 mbfp = MBopen((char *) &xs[5], TelInfo->DefaultDirVRefNum, TelInfo->DefaultDirDirID, MB_READ | MBflag);
  471.                 
  472.                 if (mbfp == 0L) {
  473.                     CRESP(fnum,11);                        /* BYU 2.4.16 */
  474.                     break;
  475.                 }
  476.                 ftpfh = 12;
  477.  
  478.                 strncpy((char *) newfile,(char *) &xs[5],PATHLEN-1);    /* BYU LSC */
  479.  
  480.                 PathNameFromDirID(TelInfo->DefaultDirDirID, TelInfo->DefaultDirVRefNum, (StringPtr) theDir);
  481.                 PtoCstr((StringPtr) theDir);
  482.                 sprintf(tempp,"remote <-- %s/%s\015\012",theDir,newfile);
  483.                 ftpmess(tempp);
  484.  
  485.                 ftpdata = ftpgo(fnum);                /* BYU 2.4.16 - open connection */
  486.                 fdport = portremoteport[fnum];
  487.  
  488.                 ftpstate = 20;        /* ready for data */
  489.                 if (ftpdata >= 0)
  490.                     SetPortType(ftpdata, PDATA);
  491.  
  492.                 CRESP(fnum,4);                            /* BYU 2.4.16 */
  493.               }
  494.             else if (!strncmp((char *) xs,"TYPE",4)) {    /* BYU LSC */
  495.                 if (toupper(xs[5]) == 'I') {
  496.                     ftptmode = FIMODE;
  497.                     if (TelInfo->MacBinary) {
  498.                         CRESP(fnum,33);                    /* BYU 2.4.16 - Binary on, MACB ON */
  499.                         }
  500.                     else {
  501.                         CRESP(fnum,34);                    /* BYU 2.4.16 - Binary on, MACB off */
  502.                         }
  503.                 }
  504.                 else if (toupper(xs[5]) == 'A') {
  505.                     ftptmode = FAMODE;
  506.                     CRESP(fnum,6);                    /* BYU 2.4.16 */
  507.                     }
  508.                 else {
  509.                     CRESP(fnum,17);                    /* BYU 2.4.16 */
  510.                 }
  511.  
  512.             }
  513.             else if (!strncmp((char *) xs,"MACB",4)) {    /* BYU LSC */
  514.                 if (toupper(xs[5]) == 'E') {
  515.                     TelInfo->MacBinary = 1;
  516.                     CRESP(fnum,25);                    /* BYU 2.4.16 */
  517.                 }
  518.                 else {
  519.                     TelInfo->MacBinary = 0;
  520.                     CRESP(fnum,26);                    /* BYU 2.4.16 */
  521.                 }
  522.                 DisplayMacBinary();            /* post an event ? */
  523.             }
  524.             else if (!strncmp((char *) xs,"PORT",4)) {    
  525. /*    get the requested port number from the command given */
  526.                 ip_addrbytes    tempaddr;
  527.                 unsigned char     *stringPtr, *tempPtr, storage[10];
  528.                 long            numbers[6];
  529.                 short index;
  530.  
  531.                 for (tempPtr = stringPtr = &xs[5], index = 0; (*stringPtr != '\0') && (index < 6);index++) {
  532.                     while ((*tempPtr != '\0') && (*tempPtr != ',')) { tempPtr++; };
  533.                      BlockMoveData(stringPtr, &(storage[1]), tempPtr-stringPtr);
  534.                      storage[0] = tempPtr-stringPtr;
  535.                      StringToNum(storage, &numbers[index]);
  536.                      tempPtr++;
  537.                      stringPtr = tempPtr;
  538.                  }
  539.                 
  540.                 tempaddr.a.byte[0] = (char) numbers[0];
  541.                 tempaddr.a.byte[1] = (char) numbers[1];
  542.                 tempaddr.a.byte[2] = (char) numbers[2];
  543.                 tempaddr.a.byte[3] = (char) numbers[3];
  544.                 portaddr[fnum] = tempaddr.a.addr;
  545.                 portlocalport[fnum] = numbers[4]*256 + numbers[5];
  546.                 fdport = portlocalport[fnum];
  547.                 CRESP(fnum,3);                            
  548.             }
  549.             else if (!strncmp((char *) xs,"QUIT",4)) {    /* BYU LSC */
  550.                 CRESP(fnum,2);                            /* BYU 2.4.16 */
  551.                 rfstate = 60;
  552.                 netputuev(CONCLASS,CONDATA,fnum,0);    /* post back to me */
  553.             }
  554.             else if (!strncmp((char *) xs,"XPWD",4) || !strncmp((char *) xs,"PWD",3)) {    /* BYU LSC */
  555.                 CRESP(fnum,14);                        /* BYU 2.4.16 - start reply */
  556.                 PathNameFromDirID(TelInfo->DefaultDirDirID, TelInfo->DefaultDirVRefNum, (StringPtr) xs);
  557.                 PtoCstr((StringPtr) xs);
  558.                 netwrite(fnum,(char *) xs,strlen((char *) xs));    /* BYU LSC - write dir name */
  559.                 CRESP(fnum,15);                        /* BYU 2.4.16 - finish reply */
  560.             }
  561.             else if (!strncmp((char *) xs,"USER",4)) {    /* BYU LSC */
  562.                 if (strlen((char *) xs) < 6)            /* BYU LSC - make sure blank name stays blank */
  563.                     xs[5] = myuser[0] = 0;
  564.                 strncpy((char *) myuser,(char *) &xs[5],16);    /* BYU LSC - keep user name */
  565.                 FTPLogUserLoggingIn();
  566.                 /* confirm log in without password */
  567.                 CRESP(fnum,10);                            /* BYU 2.4.16 */
  568.             }
  569.             else if (!strncmp((char *) xs,"STRU",4)) {    /* BYU LSC - only one stru allowed */
  570.                 if (xs[5] == 'F') {
  571.                     CRESP(fnum,18); }                    /* BYU 2.4.16 */
  572.                 else {
  573.                     CRESP(fnum,17); }                    /* BYU 2.4.16 */
  574.             }
  575.             else if (!strncmp((char *) xs,"MODE",4)) {    /* BYU LSC - only one mode allowed */
  576.                 if (xs[5] == 'S') {
  577.                     CRESP(fnum,19); }                    /* BYU 2.4.16 */
  578.                 else {
  579.                     CRESP(fnum,17); }                    /* BYU 2.4.16 */
  580.             }
  581.             else if (!strncmp((char *) xs,"ALLO",4) || !strncmp((char *) xs,"ACCT",4)) {    /* BYU LSC */
  582.                 CRESP(fnum,20); }                        /* BYU 2.4.16 */
  583.             else if (!strncmp((char *) xs,"HELP",4)) {    /* BYU LSC */
  584.                 for (i=28; i<33; i++) {
  585.                     CRESP(fnum,i); }                    /* BYU 2.4.16 */
  586.             }
  587.             else if (!strncmp((char *) xs,"NOOP",4)) {        /* BYU LSC */
  588.                 CRESP(fnum,9); }                            /* BYU 2.4.16 */
  589.             else if (!strncmp((char *) xs,"SYST",4)) {    // JMB 2.6
  590.                   netpush(fnum);                        // JMB 2.6
  591.                   netwrite(fnum, "225 MACOS System Version:\015\012", 27);    // JMB 2.6
  592.                     }    // JMB 2.6
  593.             else {            /* command not understood */
  594.                 CRESP(fnum,8);                                 /* BYU 2.4.16 */
  595.             }
  596.  
  597.             break;
  598.  
  599. /*    subroutine to wait for a particular character */
  600.         case 50:
  601.             while (0 < (cnt = netread(fnum,&xs[waitpos],1))) {
  602.                 if (xs[waitpos] == waitchar) {
  603.                     rfstate = retstate;
  604.  
  605.                     while (xs[waitpos] < 33)        /* find end of string */
  606.                         waitpos--;
  607.                     xs[++waitpos] = '\0';            /* put in terminator */
  608.  
  609.                     for (i=0; i<4; i++)                /* want upper case */
  610.                         xs[i] = toupper(xs[i]);
  611.  
  612.                     break;
  613.                 }
  614.                 else
  615.                     waitpos += cnt;
  616.  
  617.             }
  618.             break;
  619.  
  620.         case 60:                    /* wait for message to get through */
  621.                                     /* or connection is broken */
  622. /*            printf("                  %d,%d",netpush(fnum),netest(fnum));*/
  623.             if (!netpush(fnum) || netest(fnum))
  624.                 cnt = -1;
  625.             else
  626.                 netputuev(CONCLASS,CONDATA,fnum,0);    /* post back to me */
  627.             break;
  628.  
  629.         default:
  630.             break;
  631.  
  632.     }
  633.  
  634.     if (cnt < 0) {
  635.         if (mbfp) {
  636.             MBclose( mbfp );
  637.             mbfp = NULL;
  638.         }
  639.         ftpdata = dataport[fnum];                    /* BYU 2.4.16 */
  640.         if (ftpdata > 0) {
  641.             netclose(ftpdata);
  642.             netputevent(USERCLASS,FTPEND,-1,0);
  643.             dataport[fnum] = -1;                    /* BYU 2.4.16 */
  644.             mainport[ftpdata] = -1;                    /* BYU 2.4.16 */
  645.         }
  646.         rfstate = 100;
  647.         ftpstate = 0;
  648.         cnt = 0;
  649.         netclose(fnum);
  650.         SetPortType(fnum, NO_TYPE);
  651.         netputevent(USERCLASS,FTPCLOSE,-1,0);
  652. #if 0                                                /* BYU 2.4.16 */
  653.         fnum = -1;
  654.         ftpdata = -1;
  655. #endif                                                /* BYU 2.4.16 */
  656.         setftp();                /* reset it */
  657.     }
  658.  
  659.     mainstate[fnum] = rfstate;                        /* BYU 2.4.16 */
  660.     datastate[fnum] = ftpstate;                        /* BYU 2.4.16 */
  661.     retnstate[fnum] = retstate;                        /* BYU 2.4.16 */
  662.     fileport[fnum] = fdport;                        /* BYU 2.4.16 */
  663.  
  664. }
  665.  
  666. /*    important note:  for Sfread, nwant must be 256 bytes LARGER than the amount
  667.     which will probably be read from the connection.
  668.     Sfread will stop anywhere from 0 to 256 bytes short of filling nwant
  669.     number of bytes. */
  670.     
  671. long Sfread( short pnum, char *buf, long nwant)
  672. {
  673.     long    i, ndone, lim;
  674.     char    *p, *q;
  675.  
  676.     if (nwant < 1024)
  677.         return(-1);
  678.  
  679.     ndone = 0;
  680.  
  681.     HLock(mungbuf);
  682.     while (ndone < nwant - 1024) {
  683.  
  684.         if (0 >= (lim = netread(pnum,*mungbuf,1024))) {
  685.             if (ndone || !lim)            /* if this read is valid, but no data */
  686.                 return(ndone);
  687.             else
  688.                 return(-1);                /* if connection is closed for good */
  689.         }
  690.  
  691.         p = *mungbuf;
  692.         q = (char *) buf + ndone;
  693.  
  694. /*        printf("\012 lim=%d done=%d want=%d",lim,ndone,nwant);
  695.         n_row();
  696. */
  697.         for (i=0; i < lim; i++) {
  698.  
  699.             if (crfound) {
  700.                 if (*p == 10)
  701.                     *q++ = EOLCHAR;
  702.                 else if (*p == 0)
  703.                     *q++ = 13;            /* CR-NUL means CR */
  704.                 crfound = 0;
  705.             }
  706.             else if (*p == 13)
  707.                 crfound = 1;
  708.             else
  709.                 if (gFTPServerPrefs->DoISOtranslation)
  710.                 {
  711.                     *q++ = (char) ftp_iso_mac((unsigned char *)p);        /* transform to mac */
  712.                 }
  713.                 else
  714.                     *q++ = *p;                /* copy the char */
  715.  
  716.             p++;
  717.         }
  718.  
  719.         ndone = q-buf;                    /* count chars ready */
  720.     }
  721.     
  722.     HUnlock(mungbuf);
  723.     
  724.     return(ndone);
  725. }
  726.  
  727. /***************************************************************************/
  728. /*  Sfwrite
  729. *   Write an EOL translated buffer into netwrite.
  730. *   Returns the number of bytes which were processed from the incoming
  731. *   buffer.  Uses its own 1024 byte buffer for the translation (with Sfread).
  732. */
  733.  
  734. long Sfwrite( short pnum, void *buf, long nsrc)
  735. {
  736.     long    i,ndone,nout,lim;
  737.     char    *p,*q;
  738.  
  739.     ndone = 0;
  740.     HLock (mungbuf);
  741.     while (ndone < nsrc) {
  742.  
  743.         if (0 > ( i = netroom(pnum)))
  744.             return(-1);
  745.  
  746.         if (i < 1024)                    /* not enough room to work with */
  747.             return(ndone);
  748.  
  749. /*    process up to 512 source bytes for output (could produce 1K bytes out) */
  750.         if (nsrc - ndone > 512)
  751.             lim = 512;
  752.         else
  753.             lim = nsrc-ndone;
  754.  
  755.         p = (char *) buf + ndone;                /* where to start this block */
  756.         q = *mungbuf;                    /* where munged stuff goes */
  757.         for (i=0; i < lim; i++) {
  758.             if (*p == EOLCHAR) {
  759.                 *q++ = 13;
  760.                 *q++ = 10;
  761.                 p++;
  762.             }
  763.             else
  764.                 if (gFTPServerPrefs->DoISOtranslation)
  765.                 {
  766.                     *q++ = (char) ftp_mac_iso((unsigned char *)p);        /* transform to ISO */
  767.                     p++;
  768.                 }
  769.                 else
  770.                     *q++ = *p++;
  771.         }
  772.         ndone += lim;                    /* # of chars processed */
  773.         nout = q-*mungbuf;                /* # of chars new */
  774.  
  775.         
  776.         if ( nout != netwrite(pnum,*mungbuf,nout) )        /* Some error in Sfwrite */
  777.             DoError (201 | RESOURCE_ERRORCLASS, LEVEL1, NULL);
  778.         
  779.     }
  780.     HUnlock (mungbuf);
  781.     return(ndone);
  782. }
  783.  
  784.  
  785. /*    FTP receive and send file functions */
  786.  
  787. void ftpd
  788.   (
  789.     short code,
  790.     short ftpdata                            /* BYU 2.4.16 */
  791.   )
  792. {
  793.     short fnum = mainport[ftpdata];        /* BYU 2.4.16 */
  794.     short i,a;
  795.     char tempp[256];
  796.     char theDir[256];
  797.  
  798.  
  799.     ftpstate = datastate[fnum];            /* BYU 2.4.16 */
  800.  
  801.     switch (ftpstate) {
  802.         default:
  803.             break;
  804.  
  805.         case 40:                /* list file names in current dir */
  806.  
  807.             if (code == CONFAIL)    /* something went wrong */
  808.                 fcnt = -1;
  809.             if (code != CONOPEN)     /* waiting for connection to open */
  810.                 break;
  811.             
  812.             ftpstate = 41;
  813.  
  814. /*
  815. *  send the "nextfile" string and then see if there is another file
  816. *  name to send
  817. */
  818.         case 41:
  819.             netputuev(SCLASS,FTPACT,ftpdata,0);
  820.             netpush(ftpdata);
  821.             strcpy(tempp,nextfile);                    /* BYU 2.4.13 */
  822.             strcat(tempp,"\015\012");                /* BYU 2.4.13 */
  823.             i = strlen(tempp);                        /* BYU 2.4.13 */
  824.             if (gFTPServerPrefs->DoISOtranslation)
  825.                 trbuf_mac_ftp((unsigned char *)tempp, i);        /* transform to ISO */ //PETERL?
  826.             if (i != netwrite(ftpdata,tempp,i)) {    /* BYU 2.4.13 */
  827.                 CRESP(fnum,1);                        /* BYU 2.4.16 */
  828.                 fcnt = -1;
  829.                 break;
  830.             }
  831.             theDirectoryState.hFileInfo.ioFDirIndex++;
  832.             if (NULL == (nextfile = getFileName(ListingTemplate, &theDirectoryState))) {    /* normal end */
  833.                 ftpstate = 22;               /* push data through */
  834.             }
  835.             break;
  836.             
  837.         case 30:
  838.             if (code == CONFAIL)    /* something went wrong */
  839.                 fcnt = -1;
  840.             if (code != CONOPEN)    /* waiting for connection to open */
  841.                 break;
  842.             ftpstate = 31;
  843.             crfound = 0;
  844.             len = xp = 0;
  845.             filelen = 0L;
  846.             PathNameFromDirID(TelInfo->DefaultDirDirID, TelInfo->DefaultDirVRefNum, (StringPtr) theDir);
  847.             PtoCstr((StringPtr) theDir);
  848.             sprintf(tempp,"remote --> %s/%s\015\012",theDir,newfile);
  849.             ftpmess(tempp);
  850.             netputevent(USERCLASS,FTPBEGIN,-2,0);
  851.             
  852.         case 31:
  853. /*
  854. * file has already been opened, take everything from the connection
  855. * and place into the open file: ftpfh
  856. */
  857.             do {
  858.             /* wait until xs is full before writing to disk */
  859.                 if (len <= 2000) {
  860.  
  861.                     if (xp) {
  862.                         if (0 > MBwrite(mbfp, xs, xp)) {
  863.                             DoError (202 | RESOURCE_ERRORCLASS, LEVEL1, NULL);
  864.  
  865.                             MBclose( mbfp);            /* Close on Disk Full Error */
  866.                             ftpstate=22;
  867.                             CRESP(fnum,27);                /* BYU 2.4.16 */
  868.                             ftpmess((char *) messs);    /* BYU LSC */
  869.                             if( (a = netclose(ftpdata)) !=0 ) 
  870.                                 DoError (108 | NET_ERRORCLASS, LEVEL1, NULL);
  871.                             fcnt = -1;
  872.                             mbfp=NULL;
  873.                             break;
  874.                         }
  875.                         xp = 0;
  876.                     }
  877.                     len = BUFFERS;        /* expected or desired len to go */
  878.                 }
  879.  
  880.                 if (ftptmode == FAMODE)
  881.                     fcnt = Sfread(ftpdata,(char *) &xs[xp],len);    /* BYU LSC */
  882.                 else
  883.                     fcnt = netread(ftpdata,&xs[xp],len);
  884.  
  885.                 if (fcnt >= 0) {
  886.                     len -= fcnt;
  887.                     xp += fcnt;
  888.                     filelen += fcnt;
  889.                 }
  890.  
  891.                 if (fcnt < 0) {
  892.                     if (0 > MBwrite( mbfp, xs, xp)) {
  893.                         CRESP(fnum,27);            /* BYU 2.4.16 */
  894.                         MBclose( mbfp);            /* Close file on error */
  895.                         break;
  896.                     }
  897.                     MBclose( mbfp );
  898.                     ftpfh = 0;
  899.                     CRESP(fnum,5);                    /* BYU 2.4.16 */
  900.                 }
  901.  
  902.             } while (fcnt > 0);
  903.             break;
  904.  
  905.         case 20:
  906.  
  907.             if (code == CONFAIL)    /* something went wrong */
  908.                 fcnt = -1;
  909.             if (code != CONOPEN)    /* waiting for connection to open */
  910.                 break;
  911.             ftpstate = 21;
  912.             filelen = MBsize( mbfp );
  913.             towrite = 0;
  914.             xp = 0;
  915.             netputevent(USERCLASS,FTPBEGIN,-1,0);
  916.  
  917.         case 21:
  918. /*
  919. *  transfer file(s) to the other host via ftp request
  920. *  file is already open = ftpfh
  921. */
  922.             netputuev(SCLASS,FTPACT,ftpdata,0);
  923.         
  924.             if (towrite <= xp) {
  925.  
  926.                 i = BUFFERS;
  927.                 towrite = MBread( mbfp, xs, i);
  928.                 xp = 0;
  929.             }
  930.  
  931.             if (towrite <= 0 || netest(ftpdata)) {        /* we are done */
  932.                 ftpstate = 22;
  933.                 break;
  934.             }
  935.  
  936.             if (ftptmode == FAMODE)
  937.                 i = Sfwrite(ftpdata,&xs[xp],towrite-xp);
  938.             else
  939.                 i = netwrite(ftpdata,&xs[xp],towrite-xp);
  940.  
  941.  
  942.  
  943.             if (i > 0) {
  944.                 xp += i;
  945.                 filelen -= i;
  946.                 if (filelen < 0L)
  947.                     filelen = 0L;
  948.             }
  949.  
  950.             break;
  951.  
  952.         case 22:        /* wait for data to be accepted */
  953.             netputuev(SCLASS,FTPACT,ftpdata,0);
  954.  
  955.             fcnt = netpush(ftpdata);        /* will go negative on err */
  956.             if (!fcnt || netest(ftpdata))
  957.                 fcnt = -1;
  958.             if (fcnt < 0) {
  959.                 CRESP(fnum,5);                /* BYU 2.4.16 */
  960.             }
  961.             break;
  962.  
  963.         case 0:
  964.             break;
  965.  
  966.     }  /* end of switch */
  967.  
  968. /*    after reading from connection, if the connection is closed, reset up shop. */
  969.     if (fcnt < 0) {
  970.         if (mbfp) {
  971.             MBclose( mbfp );
  972.             mbfp = NULL;
  973.         }
  974.         ftpstate = 0;
  975.         fcnt = 0;
  976.         if (ftpdata >= 0) {
  977.             netclose(ftpdata);
  978.             netputevent(USERCLASS,FTPEND,-1,0);
  979.             mainport[ftpdata] = -1;                /* BYU 2.4.16 */
  980.             dataport[fnum] = -1;                /* BYU 2.4.16 */
  981.         }
  982.     }
  983.  
  984.     datastate[fnum] = ftpstate;            /* BYU 2.4.16 */
  985.  
  986. }
  987.  
  988.  
  989. /* Sftpname and Sftpuser and Sftphost
  990. *  record the name of the file being transferred, to use in the status
  991. *  line updates
  992. */
  993.  
  994. void Sftpname(char *s)
  995. {
  996.     strcpy(s, (char *) newfile);    /* BYU LSC */
  997. }
  998.  
  999. ip_addr Sftphost(void)
  1000. {
  1001.     return(hishostaddr);
  1002. }
  1003.  
  1004. void Sftpstat(long *byt)
  1005. {
  1006.     *byt = filelen;
  1007. }
  1008.  
  1009. void FTPLogUserLoggingIn(void)
  1010. {
  1011.     ftpmess("FTP user ");
  1012.     ftpmess((char *) myuser);
  1013.     ftpmess(" logging in\015\012");
  1014. }
  1015.  
  1016. /****************************************************************************/
  1017. /* Sencompass - Compute the encrypted password */
  1018. void Sencompass(char *ps, char *en)
  1019. {
  1020.     short    i,ck;
  1021.     char    *p,c;
  1022.  
  1023.     ck = 0;
  1024.     p = ps;
  1025.     while (*p)                /* checksum the string */
  1026.         ck += *p++;
  1027.  
  1028.     c = ck;
  1029.  
  1030.     for (i=0; i<10; i++) {
  1031.         *en =  (((*ps ^ c) | 32) & 127);     /* XOR with checksum */
  1032.         if (*ps)
  1033.             ps++;
  1034.         else
  1035.             c++;        /* to hide length */
  1036.         en++;
  1037.     }
  1038.  
  1039.     *en = 0;
  1040. } /* Sencompass */
  1041.  
  1042. /****************************************************************************/
  1043. /* Scompass - compute and check the encrypted password */
  1044. Boolean Scompass(char *ps, char *en)
  1045. {
  1046.     short    ck;
  1047.     char    *p,c;
  1048.  
  1049.     ck = 0;
  1050.     p = ps;
  1051.     while (*p)                /* checksum the string */
  1052.         ck += *p++;
  1053.  
  1054.     c = ck;
  1055.  
  1056.     while (*en) {
  1057.         if ((((*ps ^ c) | 32) & 127) != *en)    /* XOR with checksum */
  1058.             return(FALSE);
  1059.         if (*ps)
  1060.             ps++;
  1061.         else
  1062.             c++;            /* increment checksum to hide length */
  1063.         en++;
  1064.     }
  1065.  
  1066.     return(TRUE);
  1067. }
  1068.  
  1069. /****************************************************************************/
  1070. /*  Scheckpass - Check the password file for the user, password combination */
  1071. Boolean Scheckpass(char *us, char *ps)
  1072. {
  1073.     FTPUser        **FTPUhdl;
  1074.     Str255        scratchPstring;
  1075.     CInfoPBRec    theInfo;
  1076.     
  1077.     strcpy((char *)scratchPstring, us);
  1078.     CtoPstr((char *)scratchPstring);
  1079.     
  1080.     UseResFile(TelInfo->SettingsFile);
  1081.     FTPUhdl = (FTPUser **)Get1NamedResource(FTPUSER, scratchPstring);
  1082.     if (ResError()) return(FALSE);        // User not found
  1083.     
  1084.     HLock((Handle)FTPUhdl);
  1085.     BlockMove((**FTPUhdl).EncryptedPassword, scratchPstring,
  1086.                 Length((**FTPUhdl).EncryptedPassword)+1);
  1087.     PtoCstr(scratchPstring);
  1088.     
  1089.     if (Scompass(ps, (char *)scratchPstring)) {        // Password matches
  1090.         TelInfo->DefaultDirDirID = (**FTPUhdl).DefaultDirDirID;
  1091.         TelInfo->DefaultDirVRefNum = VolumeNameToRefNum((**FTPUhdl).DefaultDirVolName);
  1092.         WriteZero((Ptr)&theInfo, sizeof(CInfoPBRec));
  1093.         theInfo.dirInfo.ioVRefNum = TelInfo->DefaultDirVRefNum;
  1094.         theInfo.dirInfo.ioDrDirID = TelInfo->DefaultDirDirID;
  1095.         theInfo.dirInfo.ioNamePtr = scratchPstring;
  1096.         theInfo.dirInfo.ioFDirIndex = -1;        // Only give me the Directory Info
  1097.         if (PBGetCatInfoSync(&theInfo) != noErr) {
  1098.             TelInfo->DefaultDirDirID = 2;
  1099.             TelInfo->DefaultDirVRefNum = -1;
  1100.             }
  1101.         ReleaseResource((Handle)FTPUhdl);
  1102.         return(TRUE);
  1103.         }
  1104.     
  1105.     ReleaseResource((Handle)FTPUhdl);
  1106.     return(FALSE);                                    // Password was no good
  1107. }
  1108.